Repository navigation
test(e2e): repair full-suite specs that missed intentional product changes (fork notes) - #1
Closed
SimonSQLML wants to merge 333 commits into
Closed
SimonSQLML wants to merge 333 commits into
SimonSQLML wants to merge 333 commits into
Conversation
SimonSQLML
force-pushed
the
fix/e2e-main-stale-specs
branch
from
October 17, 2026 20:36
276ebfd to
1895eb1
Compare
SimonSQLML
force-pushed
the
fix/e2e-main-stale-specs
branch
from
October 20, 2026 20:46
1895eb1 to
33fe472
Compare
…one (E9) (stablyai#34063) `wsl --shutdown` can end the watch and holder with code 0. Two places only reacted to a failed exit: - the settle window that keeps a poll from reconnecting into a stopping distro; - the liveness run's 500 ms settle and running-list re-read before the verdict. On a clean exit the run read a possibly stale list that still showed the distro, and readIdentity then exec'd wsl.exe into it, booting it again. Both now use one "any watch or holder exit" predicate. Co-authored-by: Claude <noreply@anthropic.com>
…er boots (E9 follow-up) (stablyai#34093) * fix(wsl-host): no-boot connects stay quiet, and liveness recovery never boots (E9 follow-up) Two lows from the stablyai#34050 review: - A no-boot connect published "Connecting" before its running-list read, and a quiet refusal then left the row on "Connecting". It no longer publishes the pending state. - Liveness recovery reconnects only after confirming the distro runs, but that read could go stale before the reconnect spawned anything. Recovery now passes the same running check to the connection manager, which re-reads it right before spawning. Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl-host): a no-boot recovery connect still publishes its own pending status Only the default "Connecting" is skipped for a no-boot connect; an explicit status (liveness recovery's "retrying now") is still published. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…ai#34103) Same Vitest registration race as the daemon-init fix: concurrent first imports can load dependencies before pending vi.mock/vi.doMock calls are registered.
…d start after a DEBUG trap change (stablyai#29165) On bash <= 5.0 the PROMPT_COMMAND is a single scalar string. After the user changed the DEBUG trap at the prompt (`trap - DEBUG`, `trap ':' DEBUG`), Orca's preexec never saw the status-capture command, so the legacy wrapper flag stayed unset and the dispatch tail emitted OSC 133;C before the next prompt was drawn. Set __orca_in_legacy_prompt_wrapper directly in the PROMPT_COMMAND string, and re-arm the Orca DEBUG trap at the top level of that string: bash <= 4.3 (including macOS /bin/bash 3.2) restores the caller's DEBUG trap when a function returns, so the re-arm inside __orca_finish_legacy_prompt_dispatch was undone. Tests force the legacy dispatch on any bash and also run with /bin/bash on macOS. Fixes stablyai#29164 Co-authored-by: Neil <neil@stably.ai>
…ore, never replays the launch (stablyai#34054) * fix(runtime): a restored host pane resumes its agent from the hook store, never replays the launch When a WSL host's daemon restarted, the host re-created each pane with its original launch command (a fresh Codex conversation), or a plain shell for an agent typed into one: orcad has no resume record, because only layout-owner builds record hook status. A pane with no record now resumes the conversation its own hook rows name (local rows only, this workspace's), through the same pane-owned resume path a recorded session takes. Co-Authored-By: Claude <noreply@anthropic.com> * test(runtime): hook-store resume vetoes: other worktree, two sessions, shared or live elsewhere, structured host Co-Authored-By: Claude <noreply@anthropic.com> * fix(runtime): a vetoed hook-store resume launches the tab's agent fresh, as before A record read from the hook store is no promise to keep: when it is vetoed (two sessions, shared or live in another pane, no resume command) the tab's agent now launches fresh as main did, not a plain shell. Its two-session veto counts only the rows it was read from (local, this workspace), so a relayed SSH row no longer vetoes a local resume. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…ed file names (stablyai#32987) Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
…em default (stablyai#20842) The Codex switcher only rendered usage bars on inactive account rows from the per-account cache, so the active row (and System default, which never has a managed account id) showed nothing. Render the live Codex usage on the active row when this desktop owns the accounts; a remote owner's usage belongs to that host's target and stays off desktop-selected rows. Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
…s first adapter (stablyai#34088) Moves routing, machine choice, held starts, the post queue, prompt cards and owner controls out of the Slack files into a provider-neutral connector core, with Slack as the first adapter behind one adapter type. Conversation records and delivery ids are keyed by source, so Slack and Discord ids cannot collide. Behaviour-neutral for Slack apart from a slack: delivery-id prefix and a 403 (not 404) from the reply route when Slack is off. Staging's connector database is reset after deploy.
* perf(native-chat): stop hidden chats re-rendering on every tab change Skill discovery now subscribes to tab and workspace state only while the slash/skill picker is open, and the per-chat image owner subscription reads only its own workspace's tabs. Previously every mounted chat re-rendered and rescanned the tab maps on any tab change anywhere. * Resolve native chat image context from its selected owner * Cover selected chat image owners through preview consumers * Use typed reads in chat subscription performance fixture * Key chat subscription probes by fixture chat identity * Type dense chat subscription measurement results * Name the read-only floating chat resolver view * Exercise document markdown in selected-owner preview test * Check unavailable chat image through its preview dialog
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
… and cold-restores (stablyai#34095) * fix(terminal): a WSL bridge pane whose distro went away keeps its tab and cold-restores wsl --terminate (or a shutdown or crash) exits every live bridge pane with an ordinary code, so Orca closed those tabs as if the shell had exited, and the next launch opened new sessions instead of restoring the old ones. A proven exit of a WSL bridge session now checks the shared, coalesced wsl --list --running (never boots, bounded); if the distro is confirmed gone it is host loss: code -1, history left unended, tab kept, exactly as after a daemon crash. A running distro or an unanswered check leaves the exit as is, so still closes the tab. Native and SSH sessions are untouched. Co-Authored-By: Claude <noreply@anthropic.com> * fix(terminal): trust only a running-list probe that started after the exit; close a kept tab's history Review of the WSL bridge distro-loss check: - A probe already in flight from before the exit can predate the distro's boot, so it could call a user's own quick exit host loss. Only a probe that started after the exit answers; one fresh probe is chained after an older in-flight one and shared by the whole wave. - The outer bound drops to 3 s: every bridge exit waits on it. - Closing a kept tab later hit SessionNotFound before removeSession, leaking its history; an explicit close now treats that as already stopped. Co-Authored-By: Claude <noreply@anthropic.com> * fix(terminal): only a session this adapter lost to its distro may close as already gone Swallowing SessionNotFound for any id could remove the history of a session a legacy daemon (sharing the history dir) still runs. The adapter now records the sessions it turned into host loss, clears them on respawn or close, and swallows SessionNotFound on an explicit close only for those. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…ai#24032) did-start-loading fires for subframe loads too, so a page that reloads an iframe on each poll invalidated the annotation document every cycle: the pending card closed, grab mode was cancelled and saved-note markers were retired. Main-frame did-start-navigation already invalidates for every document replacement (including same-URL reloads) and same-document navigation, so drop the did-start-loading handler and move the overlay viewport reset next to that invalidation. Fixes stablyai#23988 Co-authored-by: Neil <neil@stably.ai>
… it creates (stablyai#33859) * fix(terminal): keep a brand-new remote pane's typing for the terminal it creates * fix(terminal): new-pane typing goes only to a genuinely fresh create, never an adopted or restored terminal * fix(terminal): decide a new pane looked blank at connect; at bind re-check only what the create can't cause * test(terminal): replayed history from the real restore path drops a new remote pane's typing * fix(terminal): type the replayed-history marks by xterm Terminal
stablyai#34117) The served-relay blackbox test closed the phone and data sockets from the client and sent the resume confirm before the relay had processed the close, so on a busy runner the relay correctly answered device-resume-confirmed and the test failed (about 1.8% under load). The test now closes only the phone and waits for the relay to close the data leg with 4408, which happens in the same step that marks the connection inactive. Test-only.
…stablyai#34111) * fix(orcad): find the app's bundled agent-browser driver for orca serve Desktop orcad templates omit the driver for size, so orcad materialized from an installed app reported driver_missing with ORCA_BROWSER_EXECUTABLE set. orca serve now hands orcad the app's resources copy via ORCA_AGENT_BROWSER_DRIVER; the slot's own driver still wins for standalone artifacts. Fixes stablyai#33846 * test(serve): expect the app's agent-browser driver handed to orcad * fix(serve): run a profile copy of the driver on Windows so app updates stay replaceable * fix(serve): never lend the installed Windows driver when staging fails * fix(serve): keep another launch's in-progress driver copy * refactor(serve): share claimed snapshot publication for the Windows driver copy
…yai#34074) * refactor(mobile): group native chat options and queued editing * refactor(mobile): use a concrete type import in the recording adapter
… connector reply, local only) (stablyai#33855) A connector-started agent is told it can answer in its thread with orca connector reply --text; the desktop posts the reply through its Orca Cloud connection, naming the conversation and turn, so the machine never holds a Slack token. Works for agents on this machine; elsewhere the command answers that replies aren't available from this host yet, and the turn's final message is still posted when the turn ends. Behind the experimentalConnectors setting.
…-exit, not a user close (stablyai#34083) The parked watcher passes only hostCloseReason 'pty-exit' (so the pinned guard still applies), and the local branch then let closeTab default the reason to 'user': a process exit wrote a user tombstone and retired the session. The local close now carries the pty-exit reason. Co-authored-by: Claude <noreply@anthropic.com>
…ai#34100) Adds Discord as a second connector adapter on the shared core: signed interactions for answer buttons, one gateway worker (same image, single leader by database lock, commits on the lock's connection, checkpoints for resume), thread posts through the shared post queue, owner-only control, and teammate context only from linked accounts. Inert until the Discord settings are configured. A narrow gitleaks allowlist entry covers connector Discord env var names in config errors.
* Source control actions start chats and terminals on their saved model A "start an agent" action's model lived only in free-text CLI arguments, which a native chat never reads, so AI Fix opened a chat on the default model. Each action now saves a structured model and effort that both routes apply: chat create options, or the agent's own flags in a terminal (winning over the same flag in CLI arguments). Desktop, dialog, fix-checks and mobile launches carry it; Settings rows get Model/Effort selects and the CLI arguments field says it is terminal-only. Tracked in STA-11102. * Name the model in the repository override note * Type the dialog's model hand-off; keep Agent in English in Japanese copy * fix: preserve action chat model choices through launch * Preserve action selection ownership across chat launches * Keep terminal host contract fixtures aligned with preflight * fix: wait for action Settings agent inventory * fix: consolidate direct agent routing imports * fix: use standard action option labels * fix: align action launch contracts with shared types * fix: sync action option localization metadata * test: provide action Settings inventory in mounted fixtures * Keep action options row height stable while loading * Let each Source Control action choose its chat permission mode An action's saved chat choice may now carry a permission mode, with or without a model; "Same as new chats" saves nothing. A model is replaced only when the action names one, so a permission-only choice keeps the chat's remembered model and options. * fix(native-chat): leave older hosts their own permission mode and keep action options readable - An action's saved permission mode is sent only to hosts that advertise agentSession.create.options-mode.v1. Older hosts get no mode, in create options or a later setOption, so the chat starts on that host's new-chat default, as a phone launch to such a host already does. Hosts from 1.4.225 to 1.4.227 refused a mode their tables lacked (OpenCode, Grok, OMP), leaving the action unable to start. - Settings action rows give Model and Permissions full rows in the options column so saved values are readable; the loading placeholder reserves the same rows. - Remove two unused locale keys; fix two stale comments. - Tests: the older-host create carries no permission mode; a permission mode picked alone keeps the remembered model on an acquired create. * fix(settings): reserve one options row while loading an action with nothing saved Terminal and permissions-only rows no longer shrink when loading ends; a chat agent with a model list may grow by its Model row once known. * fix(native-chat): keep the create options mode a checked literal type * fix(settings): share verified action option fields * fix(settings): keep action selectors on standard typography * Keep the launch files under their length limits after the main merge The structured route imports its result types where they are defined, and the two older-host action-launch tests share one setup helper. * One action settings section for chat and terminal launches A Source Control action's Model, model options and Permissions now apply whether it opens a chat or a terminal; terminals receive them as the agent's own flags, and a repository's own CLI arguments keep the flags it sets. Extra CLI arguments stay terminal-only. * fix(source-control-ai): one terminal projection for saved action choices Ask in a terminal now states its permission instead of leaving it to the user's own config: Claude and Grok pass --permission-mode default, Codex passes -a on-request -s read-only -c approvals_reviewer="user" (the interactive CLI has no untrusted policy, so a read-only sandbox is what asks before edits). Agents whose CLI has no flag for a mode show the existing "Applies to chats only" hint. The strict launch-preferences projection now requires the launch agent at every caller, composes model ids through the resolver's own step, carries a mode only where the agent's terminal has a flag for it, and the local string wire keeps booleans as 'true'/'false', so Cursor Thinking/Fast reach the terminal and an OpenCode permission-only choice is not refused. The argument parser knows flag arity, so removing a boolean permission flag keeps other options' values, following positionals and '--'. Pre-admission and executor share one terminal admission check on the options the terminal will receive. Customize with Save launches the recipe as it will resolve once saved; legacy partial repository overrides are edited as the complete recipe they resolve to. Empty Extra CLI arguments start collapsed. * fix(source-control-ai): an edited repository action saves complete Every Settings edit of a repository action (agent, model, permission, prompt or arguments) now starts from the complete recipe the action resolves to, whether its stored override is owned or a legacy partial. The resolved agent selection is kept (never an agent only detected to run a default), an explicit null args clear stays null, and empty args stay empty instead of being dropped. Clearing the last preference therefore means the action agent's own defaults rather than re-inheriting Global. The action text draft is lossless: unset or cleared prompt and args stay so until the user types, and the inputs show them as empty, so saving a prompt no longer writes empty args that suppress the agent's default flags. Untouched sibling actions are not rewritten by the edit. * fix(settings): style the Extra CLI arguments toggle through Button's own variant and size CI's changed-code quality check refuses restyle classes on Button and CollapsibleContent. Use the ghost variant at size xs with a margin, and put the content spacing on a plain inner wrapper. * fix: keep saved action and restart launch recipes consistent * fix: describe inherited arguments and chat-only permissions accurately * test: check repository action settings fixture type * test: map saved action options into terminal compiler inputs * fix: retain saved action controls during agent detection * fix(i18n): retire obsolete Portuguese action labels * test: align folder launch fallback mock with outcome export * fix: carry resolved connector launch intent and mode together * test: pin shared action launch branches to recorded agent output * test: preserve saved source control choices through detection and migration * test: align launch fixtures with integrated result contract * test: retain recipe and restart contracts after main integration * Unify Source Control action permission settings * Keep native Ask copy with its owning change * Preserve action drafts and old-host permission intent * Consume rejected Source Control action saves * Follow the moved Settings persistence fixture * Keep permission integration contracts in the cross-version test project * Include the action permission inheritance label in English catalogs * Align launch contracts with shared permission recipes * Keep Source Control action controls within their Settings columns * Use primitive variants for compact action settings controls * Show action arguments only for terminal defaults and widen recipe rows * Apply terminal-only action arguments visibility to repository overrides * Align action permission control with model controls * Use shared settings label for action permissions * Hide action model controls until argument migration ships
… comes due (E9 B) (stablyai#33839) * feat(wsl-host): start a WSL host's distro when one of its automations comes due E9 connect policy, part 2. A WSL host's automations run inside its distro, so a distro that is off (a reboot, an idle release) missed them. While a host is connected the desktop now reads its enabled automations' next run (on connect and every 15 min) and keeps the soonest one per host in userData. When that time comes with the host off, it boots the distro once, and orcad's startup catch-up fires the run within its missed- run grace. A run due while the computer was off fires once Orca starts. Nothing wakes past the grace window, and a connected host is left to its own scheduler. Co-Authored-By: Claude <noreply@anthropic.com> * test(wsl-host): a due automation boots a parked host once, never with WSL hosts off Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl-host): keep the following run, and forget changed automations (E9 review) Review of stablyai#33839: - A run handled while connected dropped the host's next due time. The wake now keeps each host's enabled schedules and computes the following run locally whatever happens to this one (wake failed, past grace, handled by the host), and re-reads the real one from a connected host. - A deleted, disabled or rescheduled automation kept waking the distro at its old time. A successful automation.create/update/delete from this desktop now re-reads the host's automations, as do the 15-minute re-read and every connect. Nothing boots a distro to check: on wake, a distro already running is just reconnected. - wakeForAutomation/isConnected live here now (moved out of stablyai#33838); isConnected reads the host's reachability, never booting. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(wsl-host): say isConnected answers for this process; keep the service in bounds isConnected reports whether the host answers through this process; false is not "stopped" (a fresh process has no bridge yet, and the wake just connects). The service's quiet record read moves beside the other record helpers so the file stays within its line limit after the E9 additions. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(wsl-host): give the connector contract its own file; one wake path for focus and automations After rebasing onto stablyai#34063, stablyai#34093 and stablyai#33110 the WSL host service was over its line limit. The connector contract (what the service drives) moves to wsl-host-connector-contract.ts, re-exported from the service, and the focus entry and the automation wake share one private wake step: lift the park, then reconnect unless the host answers, read with stablyai#33110's focusReachability so neither pays a WSL round trip when this process has no bridge yet. An automation wake no longer reconnects a host that already answers. Co-Authored-By: Claude <noreply@anthropic.com> * test(wsl-host): an automation wake with no bridge skips the reachability probe Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…e test (stablyai#34115) Freezes the connector's shipped table definitions: later schema changes must be additive statements. Adds a baseline fixture and an upgrade test (baseline, then current schema, compared with a fresh database on SQLite and Postgres), plus the statement-shape check relay already uses. No runtime change.
…yai#14765) Codex paginated rollouts persist an item_completed ContextCompaction item with no content, and legacy rollouts persist an event_msg context_compacted. The Codex decoder dropped both, so the native Chat timeline never showed that context was compacted. Emit a system row with the shared compaction copy and presentation so it renders as the compaction divider. Fixes stablyai#14188 Co-authored-by: Neil <neil@stably.ai>
…oml (stablyai#33999) Jcode accepts a string or an array of strings per hook event, but Orca's [hooks] parser only understood single-line strings, so any array made status and install report error and no hook was written. Parse string arrays, append Orca's command as the last element (after the user's pre_tool gates), repair a stale Orca element in place, collapse duplicate managed elements on reinstall, and remove only Orca's element on uninstall. Edits are offset splices on the original text, so user entries, comments and layout survive; malformed or non-string arrays still fail closed. Fixes stablyai#33998 Co-authored-by: Neil <neil@stably.ai>
… revert them (stablyai#34414) QuickCommandsPane, useAddRepoCloneFlow, UntitledFileRenameDialog and the workspace board column resize hook guarded a render-phase setState with a ref written in the same render. When a sibling suspends, React discards that render and its queued updates but keeps the ref write, so the retry skipped the adjustment (no Add dialog, empty clone destination, stale save-as name, stale column width). Track each guard in state instead, and sync the column-resize handler refs in a layout effect. The other two sites from the issue (WorktreeMetaDialog prevIsOpenRef and use-native-chat-draft lastScopeKey) no longer exist on main: the dialog remounts a keyed draft and the chat draft reads via useSyncExternalStore. Fixes stablyai#25527 Co-authored-by: Matheus Breguêz <matbrgz@gmail.com>
…i#33190) An unexpected ACP agent exit reported only the whole-run stderr tail, so a startup warning read as the cause, and the observed exit code/signal was dropped. Add the exit code or signal to the ended reason and Details, file the stderr tail as a log diagnostic like the Claude and Codex lanes, and read the exit status from ManagedProviderProcess.exitStatus through a shared formatter that Claude reuses. Fixes stablyai#33035 Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Co-authored-by: Neil <neil@stably.ai>
…rbatim (stablyai#14037) Without --enter, --text reaches the PTY unmodified, so integrators can send Escape or Ctrl+U directly. With --enter and without --interrupt, prompts to a recognized running agent are bracketed-pasted and embedded Escape is made inert. Fixes stablyai#14032 Co-authored-by: Neil <neil@stably.ai>
…ment while scrolling (stablyai#34267) Scroll-spy pages rewrite the URL fragment with history.replaceState as you scroll. The webview navigation handlers and setBrowserPageUrl treated those same-document updates as a new document, retiring saved-note badges and cancelling an open comment card. Fragment-only in-place updates now keep the geometry; document navigations and in-place route changes (path or query) still retire it, and the store no longer guesses document boundaries from URL changes.
…tablyai#11359) * fix(windows): probe fnm's real default alias dir for Node fallback On Windows, fnm stores the default alias under FNM_DIR, else %APPDATA%\fnm (legacy ~\.fnm), and node.exe sits directly in aliases\default with no bin subdir. Probe those dirs and append them to PATH so fnm's default only backfills a missing Node instead of shadowing an inherited one. Fixes stablyai#11356 Co-authored-by: niceSprite <16523864+iFwu@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> * test: keep onTestFinished callbacks returning void --------- Co-authored-by: Neil <neil@stably.ai> Co-authored-by: Claude <noreply@anthropic.com>
…u rows (stablyai#34047) * fix(mobile): build the Source Control action sheet from desktop's menu rows Adds Force Push and desktop's order, enable rules and hints. * fix(mobile): rebase from desktop's effective base and keep the Force Push warning in the action sheet * fix(mobile): keep the rebase row's base when the branch compare fails * fix(mobile): keep upstream compares working when the default base lookup fails * fix(mobile): keep the rebase target apart from the branch compare so failed or unsupported compares keep it * fix(mobile): leave force pushes to desktop when the linked review has its own push target * refactor(mobile): rebase onto the shown base and share the force-push block with the primary action
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…b page probe (stablyai#34427) The title and icon-link regexes rescanned the rest of the body from every unclosed opener, so a 192 KB page of repeated '<link ' or '<title>' blocked the main or runtime event loop for seconds. Scan tags forward only.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…unt it will start on (stablyai#34429) * fix(native-chat): list a resting Claude chat's / commands from the account it will start on A resting chat's next start follows the selected Claude account, but its / menu was read from the account saved when the chat was created. Read it from the same account a new chat would be created on, and rescan when the selection changes. * refactor(native-chat): resolve the at-rest account in the shared catalog so its key matches the scan * test(native-chat): build the second at-rest chat record from a lease fixture
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…nd session option picks (stablyai#33977) * fix(mobile): resolve terminal chat agents in desktop's order Mobile now uses the shared detected-then-launch precedence and transcript-readability check; the phone's remembered agent only fills in after them. * fix(mobile): hide Codex foreground commands from the background-task strip * refactor(native-chat): share diff-card gutter, basename and task count * fix(mobile): show clipped tool output sizes in KB/MB like desktop * refactor(native-chat): share the tool-run header rules with mobile * fix(native-chat): share tool-line detail rules; skip unsafe-only search hits * fix(mobile): copy message text with desktop's rule Copy now leaves out roster and background-task fallback twins and wordless provider frames. * refactor(native-chat): memoize shared tool-line view and output sizes; share result preview * fix(native-chat): read a lone result's preview from its narrowed body * chore(i18n): ship chat tool and stop copy in the runtime English catalog * refactor(native-chat): move the pending-send echo rule to shared Mobile reuses it instead of its own matcher. * fix(mobile): match chat echoes after their send boundary, sink unmatched ones Uses desktop's rule: rows before the send no longer retire an echo, a send that never lands no longer lets later glued sends retire, and an unmatched echo sits below later turns. * fix(mobile): keep glued photo captions and folded boundaries in echo matching * fix(mobile): give image preview echoes the send time the occurrence rule reads * fix(mobile): match echoes on image-normalized rows and cap open sends at eight Same input and bound as desktop; each open send rescans the transcript. * test(mobile): drop a pending-order case the tail test already covers * refactor(mobile): read the send boundary once and skip echo normalization when idle * test(native-chat): type the occurrence case's pending send * test(mobile): drop the pending-echo wall-clock entry from the flaky-test baseline * refactor(native-chat): share session option labels with mobile Mobile's options pill now shortens effort levels (Med, XHigh, Min) and names choices and options the way desktop does, from one English table that desktop translates. * refactor(native-chat): run mobile terminal chat options on the desktop surface The terminal-chat option surface, its appliers, the option cache and the dispatch types move to src/shared, and the phone builds its pickers from them. Grok and every other agent with a catalog now get model and effort pickers on the phone, picks are saved as the host's launch defaults, the OMP live switch gate and discovery mapping come from one copy, and authoritative discovery retires persisted models it no longer lists. The option stamp moves to shared. * refactor(mobile): merge the session option type imports * fix(mobile): keep terminal chat option picks on their own chat The phone keeps one option surface per chat, so a pick that lands after leaving and returning shows there, and a picker command only switches the chat it came from. Discovered models merge with the seed catalog as on desktop, so Grok keeps its effort picker. A Claude model switch the phone cannot confirm is never saved as a launch default. * fix(mobile): start terminal chat options over when a tab changes agent A tab that runs another agent drops its kept option surfaces, report markers and cached record, so a fresh session shows its own model. A pick that lands after the phone moved to another chat is not saved as a launch default. * fix(mobile): fence retired terminal chat option surfaces A write that lands after its tab started another agent no longer publishes the old agent's record, and a changed OMP switch capability rebuilds the chat's surface from the cache instead of reviving an older one. * refactor(native-chat): simplify the shared session option wiring Desktop translation pieces use literal English defaults so the localization gate can read them, the selected-choice lookup is shared once, and the phone keeps one option surface per tab with the agent change detected from the cached record. * refactor(mobile): return no option surface for an agent without a catalog * test(native-chat): expect the shared Effort label in the startup picker test * test(native-chat): keep only the label cases main still checks after the rebase * refactor(native-chat): import the session option snapshot rules once in the PTY option surface * refactor(native-chat): share structured option pick bookkeeping with mobile Desktop and the phone now track picks per option through one shared book: a repeat of an option on its way waits, other options go together, a lost reply is not a pick done, and a stale reply only commits its own option. The phone also re-reads options each turn and after the provider starts, and shows picks at once while the host is still starting the provider. * refactor(native-chat): share the option pick blocking rule * fix(native-chat): read in-flight option picks from the shared book for launch send options * fix(native-chat): keep the structured options hook within its line budget and pass the phone turn in the e2e harness
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…#34440) * refactor(pty): colocate IPC test fixtures with PTY owners * test: exclude PTY test constants from credential source census
…34443) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…op and the chat composer (stablyai#34000) * refactor(mobile): share the queued-card projection with desktop Image-only queued drafts showed a blank card on the phone. * fix(mobile): honor the host's Queue follow-ups setting With it off, a mid-turn send from the phone still queued while desktop sent it into the running turn. * fix(mobile): keep a queued-card edit when the card leaves the queue The phone closed the editor and dropped the typing; it now goes to the chat box as on desktop. * fix(mobile): hold /clear and /compact for background work and sends The phone fired the command where desktop holds it, showed start failures twice, and left the agent unnamed in failures. * fix(mobile): hand a queued edit back to the chat it came from * fix(mobile): scope a command's send hold to its own chat * fix(mobile): read a published null queue as empty * refactor(mobile): share the returned queued-card caption rule * test(mobile): drop queued-card tests the shared rules already own * refactor(native-chat): share the needs-attention rule and drop leftover wrappers * fix(mobile): type the structured sends mock, drop the moved queued-cards path and ship queued edit copy at boot * fix(native-chat): drop the queued card's unused image-label import after the rebase * fix(mobile): order the phone's queue reorder preview by position, as the shared cards sort * test(mobile): keep the queued-messages test within its line budget * fix(mobile): settle terminal chat working state and turn timing with desktop's rules Move desktop's live-status merge, Stop suppression, hook-state resolver and terminal turn timing to src/shared/native-chat. Mobile reads the transcript lifecycle the host already sends, so a provider turn end settles Working the same way desktop does. Terminal chats now get the turn bar, timer and folding, and the streaming preview uses the shared deriveNativeChatStreamingText. * fix(mobile): send desktop's terminal Stop keys, a second Escape only for OpenCode Desktop sends one Escape on Stop. It adds a paced second Escape only for OpenCode, which confirms an interrupt that way. Claude Code and Codex read Esc-Esc at an idle prompt as rewind. The rule moves to native-chat-agent-support, and the phone now paces the second Escape at desktop's answer step instead of 80ms. * fix(mobile): word Orca-stop and usage-limit notices like desktop Move desktop's Orca-stop sentences to src/shared with an English table that desktop translates. The phone names the Orca host it pairs with, and when that host is unnamed it says "the remote server". Usage-limit rows rebuild desktop's sentence from the failure fact. The usageLimitLineText fallback, which only the phone used, is deleted. * test(mobile): pass the overlay's host name in the prompt controller harness * test(mobile): re-record Stop goldens at desktop's step, split status-notice tests, pin the turn clock and ship notice copy at boot * fix(mobile): offer structured Stop while a send is out and read queue-sends-next as working Move desktop's structured Stop rule, its Stop-joining helpers and the queue-sends-next rule to src/shared. Both sides now use them. The phone counts its in-flight sends, so a conversation-stop host offers Stop before the turn opens. Between queued turns the phone reads as working, and commands that can't wait in line hold like they do on desktop. Untargeted Stops are no longer joined on legacy hosts. * fix(mobile): offer terminal Stop again when its Escape went nowhere Stop hides Working on the phone like it does on desktop. The phone's Escape can fail outright, though, while desktop writes to a local PTY. When no Escape could have landed, the phone now drops that suppression. The streaming preview also treats a pending echo as the transcript's tail, as desktop does, so an earlier reply can't hide a new preview. * fix(mobile): hold structured Stop while a send it covers is in flight On desktop, Stop's held and Stopping state depends on whether the chat can stop, and that includes a send still in flight. The phone now does the same. Once Stop is pressed before the turn opens, the button holds and repeated presses send no more untargeted cancels. * fix(mobile): end the terminal Stop hold when a new message is sent Desktop clears Stop's working suppression on an optimistic send, so a new turn that keeps the same hook epoch (Claude with working subagents) still offers Stop. The phone now does the same when a new pending echo appears. * refactor(mobile): trim chat turn wiring after the desktop rule move Drop the controller's unread nativeChatAgentWorking field. Re-render only when a chat starts or stops having a send out. Keep the structured turn indicator stable across stream frames. Type the Stop test table instead of casting. * refactor(mobile): track structured sends in flight once for Stop and command holds * test(mobile): re-record Stop goldens now that Stop settles with its Escape delivery * fix(mobile): escape terminal image paths like desktop drops * fix(mobile): keep launch-draft prefill over older user turns * fix(mobile): rank @ file matches with desktop's fuzzy Quick Open search * fix(mobile): use desktop's composer triggers for mid-prompt / and $ picks Picked @ files are now quoted when the path has spaces. * fix(mobile): send picked skill paths on structured chats * fix(mobile): list the host's disk-scanned skills in the / and $ menus The phone names the workspace and the host resolves its folder, refusing SSH workspaces as desktop does; hosts without skills.discover-workspace.v1 list none. * fix(mobile): forget a picked skill once its token is deleted * fix(mobile): drop a picked skill as soon as its token is deleted, and retry failed skill scans * fix(mobile): treat a picked leading skill as chat and stop failed skill scans from refiring * test(mobile): drop the menu ranking case the shared picker tests own * refactor(mobile): keep skill picks on the draft record and reuse shared send rules A rejected send now keeps its picks and leading-skill origin on both send paths. * fix(mobile): replace a re-picked skill's file and restore picks with a rejected send * fix(mobile): read the chat agent for the skill catalog from the active resolution * style(native-chat): format the composer autocomplete files * fix(native-chat): import the picker's apply and send-classify rules from the shared composer module * refactor(mobile): import the composer's draft-store hooks once * style(mobile): format the notice row's style import
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…34449) * refactor: group Claude structured session lifecycle owners * refactor: consolidate retargeted Claude state type imports
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Align still-stale e2e expectations with shipped product behavior: - the Cmd+J placeholder names workspaces and tasks - the worktree meta dialog is titled "Workspace details" - OS-opened CSV/TSV files are editable and render as an ARIA grid - the delayed-save notice carries the app toaster's close button Fixes stablyai#30114 Co-authored-by: Neil <neil@stably.ai>
nwparker
force-pushed
the
fix/e2e-main-stale-specs
branch
from
October 27, 2026 16:28
33fe472 to
0fba66c
Compare
Since stablyai#33270, Create worktree reads Linear status from the repo's host (linear:status IPC) instead of the store, so the store-only fixture left Linear disconnected in the composer and the pasted URL was never looked up. Stub the linear:status handler with the same connected status.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
업데이트 (2026-10-17)
cf6a5446a6) 위로 rebase했습니다.mobile-subscribe-idle-hidden-pane-fit: upstream에서 수정돼 실패 목록에서 빠졌습니다.tasks-page,native-chat-zcode-transcript,github-created-issue-start-prefill,layout-compat-old-phone-on-new-server.배경
근거가 된 main E2E 실행
이 PR이 고치는 것
1. CI 버그: 전용 lane spec이 일반 shard에 섞임
config/scripts/ci-e2e-shard-plan.mjs가 Playwright 전체 discovery를 그대로 shard에 나눕니다.workspace-layout-oracle-headless.spec.ts가 orcad 빌드가 없는 일반 shard에서 돌고,CI=1이면 skip이 금지돼 9개가 매번 실패합니다.ci-e2e-job-selection.mjs의isDedicatedE2eSpec로 전용 spec(orcad, managed SSHssh-orcad-*, native IME, Windows 전용)을 shard 계획에서 제외합니다. changed-spec job이 이미 쓰던 기준과 같습니다.foo.spec.ts)이고 전용 목록은 repo 기준(tests/e2e/foo.spec.ts)이라 앞에tests/e2e/를 붙여 비교합니다.ci-e2e-shard-selection.test.mjs.2. 제품의 의도된 변경을 못 따라간 spec (테스트만 수정, 제품 코드 무변경)
linear-url-workspace-entry,paired-cmd-j-host-qualified-tabs,workspace-emoji-picker,worktree-jump-palette-filteradd-project-error-toast-stackingprofile-state-save-delayworkspace-emoji-pickeros-opened-documents(csv, tsv)table이 아닌 ARIAgrid로 렌더링됨.data-testid="csv-grid"로 role 무관하게 찾도록 변경ai-vault-panel-searchdisabled/no-service응답은 그 호스트를 title-only 모드로 고정함 (stablyai#22453). 옛 에러 문구 대신 title-only 문구를 기대하고, 이유마다 패널을 remount하도록 재작성mobile-subscribe-idle-hidden-pane-fitpairedRuntimeConnectionFromOffer로 감쌈검증
build:electron-vite:parallel --mode e2e,CI=1 SKIP_BUILD=1).아직 안 고친 것 (다음 세션 할 일)
로컬에서 모두 재현됩니다. 문구 변경이 아니라 런타임 디버깅이 필요합니다.
실제 제품 버그 가능성 높음
markdown-find-adversarial(2개): 찾기 입력창에 포커스한 상태에서 에디터를 Shift-클릭하면 선택이 직전 클릭 위치가 아니라 문서 맨 처음부터 잡힙니다. 프로브 결과 DOM selection이 "Adversarial Find interactions\nNeedle first match..."로 시작했습니다. 의심 지점:src/renderer/src/components/editor/rich-markdown-search-focus.ts의 Shift 분기view.focus(). Replace 입력 포커스 복귀 실패도 같은 계열로 보입니다.markdown-review-selection-performance: 클릭 후 Shift+ArrowRight로 선택해도 "Add review note" 버튼이 안 뜹니다. 버튼은RichMarkdownAnnotationOverlay.tsx에 남아 있고, target 계산(rich-markdown-review-annotations.ts의getRichMarkdownAnnotationTarget)을 확인해야 합니다.tab-strip-tab-render-isolation: 백그라운드 탭 제목 하나를 바꾸면 커밋당 탭이 1개가 아니라 2개 다시 렌더링됩니다. 성능 회귀 가능성이 있습니다.원인 미확인
terminal-attention: 포커스된 탭에 BEL을 보내도 unread가 안 됩니다.terminal-pane-title-strip-placement: 제목 strip에 드롭해도 해당 pane이 활성화되지 않습니다.terminal-split-pane-paste-ownership: 내부 파일 드롭이 대상 PTY에 쓰이지 않습니다.landing-preflight-runtime-routing: 클라이언트 PATH를 빈 폴더로 바꿔도preflight.check().git.installed가 true입니다. 로컬 probe(src/main/ipc/preflight-command-exec.ts)가 PATH 밖 설치 경로도 찾기 때문으로 추정되지만,/usr/bin은 그 목록에 없어 확인이 필요합니다.github-project-board: 드래그 후 빈 컬럼에 카드가 나타나지 않습니다.jira-panel-layout: 폭별로 제목 너비가 200px 초과여야 하는데 190px입니다. fix(jira): keep issue titles readable in narrow panels stablyai/orca#28583/feat(jira): choose planning columns in the issue list stablyai/orca#28615 이후 컬럼 추가 영향으로 보입니다. 어느 폭에서 실패하는지 아직 모릅니다.native-chat-ask-user-question-card: Submit 버튼이 나타나지 않습니다.wsl-host-fake-transport: 가끔 실패합니다.별도 이슈
paired-remote-terminal-parked-scrollback-restarthard-kill (e2e: paired-remote-terminal-parked-scrollback-restart hard-kill case fails on main (Linux) stablyai/orca#29679): CI에서는 통과합니다(run 38906248356 로그:tokenAfterReveal: true). 관리자 로컬(openclaw)에서만 실패합니다.pnpm typecheck:e2e는 main에서 오류 261개로 깨져 있고 CI에서 강제되지 않습니다. 이 범위 밖입니다.우리 PR(stablyai#29543, stablyai#29592) 재검토 결과
--config config/vitest.config.ts필요).session-tabs.ts168, 196-200행 부근): 호스트 publish 전에 alias로 구독하면 프레임이 alias 철자로, publish 후에 구독하면 호스트 철자로 옵니다. 데스크톱 렌더러는 frame의worktree로 탭을 보관하므로(apply-snapshot.ts), alias를 쥔 클라이언트가 늦게 구독하면 탭이 여전히 비어 보일 수 있습니다. 데스크톱은 보통 worktree 목록에서 호스트 철자를 받으므로 노출은 작습니다.session-tabs.ts241행 부근.subscriptionId없이 unsubscribe하면<key>:접두사로 지워서 folder workspace 인스턴스나:이 들어간 POSIX 경로의 형제 스트림까지 끊을 수 있습니다.로컬 재현 환경
G:\wsl\Ubuntu로 옮겼습니다. 원래 C:에 있던 디스크가 빌드로 커지면서 C:가 꽉 차서 옮긴 것입니다.~/orca, shadbc1e18b이고 이 브랜치 변경이 적용돼 있습니다. Node 24는 nvm으로 설치했습니다.VITE_EXPOSE_STORE=true pnpm run build:electron-vite:parallel --mode e2e로 다시 빌드해야 합니다.🤖 Generated with Claude Code